package org.jwos.plugin.file.web;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.jwos.platform.domain.GlobalSession;
import org.jwos.platform.domain.User;
import org.jwos.platform.service.SessionManager;
import org.jwos.plugin.file.domain.FileUploadInfo;
import org.jwos.plugin.file.service.FileManager;
import org.jwos.plugin.file.util.ObservedInputStream;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class FileUploadServlet extends HttpServlet {
	
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException {		

		try {
			request.setCharacterEncoding("UTF-8");
			
			boolean isMultipart = ServletFileUpload.isMultipartContent(request);
			if(isMultipart) {				
				ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
				SessionManager sessionManager = (SessionManager)context.getBean("sessionManager");
				FileManager service = (FileManager)context.getBean("fileManager");
				
				ServletFileUpload upload = new ServletFileUpload();
				upload.setHeaderEncoding("UTF-8");

				String sessionId = null;
				String folderId = null;				
				String fullName = null;				
				ObservedInputStream input = null;
				User user = null;
				
				FileItemIterator iter = upload.getItemIterator(request);
				FileItemStream item = iter.next();				
				//swfuploader
				if(item.getFieldName().equals("Filename")) {
					//Filename
					fullName = readStringFromStream(item.openStream());
					while(iter.hasNext()) {
						item = iter.next();
						//sessionId					
						if(item.getFieldName().equals("sessionId")) {
							sessionId = readStringFromStream(item.openStream());
							user = sessionManager.getUserBySessionId(sessionId);
							if(user==null) {
								response.sendError(HttpServletResponse.SC_FORBIDDEN);
								return;
							}
						}
						//folderId
						if(item.getFieldName().equals("folderId")) {
							folderId = readStringFromStream(item.openStream());
						}
						//Filedata
						if(item.getFieldName().equals("Filedata")) {
							input = new ObservedInputStream(item.openStream());
							service.createFile(sessionId,folderId, fullName, input);
						}
					}					
				} else {
					String postbackId = null;
					GlobalSession session = null;
					//sessionId					
					if(item.getFieldName().equals("sessionId")) {
						sessionId = readStringFromStream(item.openStream());
						user = sessionManager.getUserBySessionId(sessionId);
						if(user==null) {
							response.sendError(HttpServletResponse.SC_FORBIDDEN);
							return;
						}
					}
					while(iter.hasNext()) {				
						item = iter.next();
						//folderId
						if(item.getFieldName().equals("folderId")) {
							folderId = readStringFromStream(item.openStream());
						}
						//postbackId
						if(item.getFieldName().equals("postbackId")) {
							postbackId = readStringFromStream(item.openStream());
						}
						//Filedata
						if(item.getFieldName().equals("Filedata")) {
							session = sessionManager.getGlobalSession(sessionId);
							fullName = item.getName();
							input = new ObservedInputStream(item.openStream());	
							FileUploadInfo info = new FileUploadInfo(input,request.getContentLength());							
							try {
								session.setAttribute(postbackId, info);
								service.createFile(sessionId,folderId, fullName, input);
							} finally {
								session.removeAttribute(postbackId);
							}							
						}						
					}
				}
				
//				List items = initFileUpload(request);
//				Map paraMap = getParameterMap(items);
//				
//				String sessionId = (String)paraMap.get("sessionId");
//				String folderId = (String)paraMap.get("folderId"); 
//				String fileName = (String)paraMap.get("fileName");
//				String fileType = (String)paraMap.get("fileType");
//				String fullName = fileName + (fileType!=null && fileType.length()>0 ? "."+fileType : "" );   
//				int fileSize  = ((Integer)paraMap.get("fileSize")).intValue();				
//				
//				User user = sessionManager.getUserBySessionId(sessionId);
//				if(user!=null) {
//					FileManager service = (FileManager)context.getBean("fileManager");				
//					FileItem fileItem = getUploadFileItem(items);
//					service.createFile(sessionId,folderId, fullName, fileSize, fileItem.getInputStream());
//				} else {
//					response.sendError(HttpServletResponse.SC_FORBIDDEN);
//				}								
			} 
		} catch (Exception e) {
			e.printStackTrace();
			throw new ServletException(e);
		} finally {
			
		}
	}
	
	private Map getParameterMap(List items) {
		Map map = new HashMap();
		
		try {
			for(int i=0;i<items.size();i++) {
				FileItem item = (FileItem) items.get(i);
			    if (item.isFormField()) {
					String name = item.getFieldName();
					String value = item.getString("UTF-8");
					map.put(name, value);
				} else {
					Integer fileSize = new Integer((int)item.getSize());
					map.put("name", item.getName());
					map.put("fileSize", fileSize);			
				}
			}
			
			String name = map.containsKey("Filename") ? (String)map.get("Filename") : (String)map.get("name");			
			String fileName = "";
			String fileType = "";
			if(name!=null && name.trim().length()>0) {
				name = name.trim();
				int index = name.lastIndexOf(".");
				if(index>0) {
					fileName = name.substring(0,index);
					if(index+1<name.length()) {
						fileType = name.substring(index+1, name.length());
					}
				} else {
					fileName = name;
				}
			}
			map.put("fileName", fileName);
			map.put("fileType", fileType);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		return map;
	}
	
	private FileItem getUploadFileItem(List items) {
		FileItem fileItem = null;
		
		Iterator iter = items.iterator();
		while (iter.hasNext()) {
		    FileItem item = (FileItem) iter.next();
		    if (!item.isFormField()) {
		    	fileItem = item;
		    	break;
			}
		}
		
		return fileItem;
	}	
	
	private List initFileUpload(HttpServletRequest request) throws FileUploadException {		
		DiskFileItemFactory factory = new DiskFileItemFactory();
		factory.setSizeThreshold(10240000);
		ServletFileUpload upload = new ServletFileUpload(factory);
		upload.setHeaderEncoding("UTF-8");
		return upload.parseRequest(request);	
	}
	
	private String getSimpleFileName(String fileName) {		
		return new File(fileName).getName();
	}
	
	private String getFileName(String fullName) {
		String fileName = "";
		
		if(fullName!=null && fullName.trim().length()>0) {
			fullName = fullName.trim();
			int index = fullName.lastIndexOf(".");
			if(index>0) {
				fileName = fullName.substring(0,index);				
			} else {
				fileName = fullName;
			}
		}
		
		return fileName;
	}
	
	private String getFileType(String fullName) {
		String fileType = "";
		
		if(fullName!=null && fullName.trim().length()>0) {
			fullName = fullName.trim();
			int index = fullName.lastIndexOf(".");
			if(index>0) {
				if(index+1<fullName.length()) {
					fileType = fullName.substring(index+1, fullName.length());
				}
			}
		}
		
		return fileType;
	}
	
	private String readStringFromStream(InputStream is) {
		String string = null;
		
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			byte[] buff = new byte[1];
			int bytesRead;
			while (-1 != (bytesRead = is.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
			bos.flush();
			bos.close();
			string = bos.toString("UTF-8");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		return string;
	}
}
